﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kokomo.Environment.Hosting;
using System.Windows;

namespace Kokomo.Environment.Services
{
	/// <summary>
	/// Exposes services provided by the environment.
	/// </summary>
	public static class EnvironmentServices
	{
		/// <summary>
		/// Gets a service implemented by the environment.
		/// </summary>
		/// <typeparam name="TService">The type of service.</typeparam>
		/// <returns>An instance of <typeparamref name="TService"/> provided by the environment, if available;
		/// otherwise, <c>null</c>.</returns>
		public static TService GetService<TService>()
			where TService : class
		{
			EditorApplication app = Application.Current as EditorApplication;
			if (
				(app == null)
				|| (!app.IsCompositionEnabled)
				|| (app.Container == null)
				) return null;

			IServiceProvider services = app.Services;
			if (services == null) return null;

			TService service = (TService)services.GetService(typeof(TService));
			return service;
		}
		/// <summary>
		/// Gets a service implemented by the environment, or throws an exceptin if the service is not available.
		/// </summary>
		/// <typeparam name="TService">The type of service.</typeparam>
		/// <returns>An instance of <typeparamref name="TService"/> provided by the environment.</returns>
		/// <exception cref="MissingServiceException">The requested service is missing.</exception>
		public static TService DemandService<TService>()
			where TService : class
		{
			TService service = GetService<TService>();
			if (service == null)
				throw new MissingServiceException(typeof(TService));

			return service;
		}
		/// <summary>
		/// Gets extensions implementing a contract.
		/// </summary>
		/// <typeparam name="TExtension">The type of extension.</typeparam>
		/// <param name="contractName">The name of the contract, or <c>null</c>.</param>
		/// <returns>A list of extension objects.</returns>
		/// <remarks>
		/// This method discovers extensions via composition,
		/// and depends on the application settings.
		/// </remarks>
		public static IEnumerable<Lazy<TExtension>> GetExtensions<TExtension>(
			string contractName = null
			)
		{
			EditorApplication app = Application.Current as EditorApplication;
			if (
				(app == null)
				|| (!app.IsCompositionEnabled)
				|| (app.Container == null)
				) return new Lazy<TExtension>[0];

			return app.Container.GetExports<TExtension>();
		}

		#region Servces
		/// <summary>
		/// Gets the <see cref="IDocumentManager"/> service.
		/// </summary>
		public static IDocumentManager DocumentManager { get { return DemandService<IDocumentManager>(); } }
		/// <summary>
		/// Gets the <see cref="IUiService"/> service.
		/// </summary>
		public static IUiService UiService { get { return DemandService<IUiService>(); } }
		/// <summary>
		/// Gets the <see cref="ISettingsManager"/> service.
		/// </summary>
		public static ISettingsManager SettingsManager { get { return DemandService<ISettingsManager>(); } }
		#endregion
	}
}
